/*
 * This file is part of b.AMP.
 *
 * b.AMP is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * b.AMP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with b.AMP.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __BAMP_VALUE_H__
#define __BAMP_VALUE_H__

#include <bamp/rc.h>
#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif


/**
 * Type IDs. These are used to transmit typed information in a generic
 * way.
 */
typedef enum
{
    BAMP_TYPE_NULL   =  0, /// No value at all
    BAMP_TYPE_U8     =  1, /// 8-bit unsigned integer
    BAMP_TYPE_U16    =  2, /// 16-bit unsigned integer
    BAMP_TYPE_U32    =  3, /// 32-bit unsigned integer
    BAMP_TYPE_U64    =  4, /// 64-bit unsigned integer
    BAMP_TYPE_I8     =  5, /// 8-bit signed integer
    BAMP_TYPE_I16    =  6, /// 16-bit signed integer
    BAMP_TYPE_I32    =  7, /// 32-bit signed integer
    BAMP_TYPE_I64    =  8, /// 64-bit signed integer
    BAMP_TYPE_F32    =  9, /// 32-bit IEEE 754 floating point number
    BAMP_TYPE_F64    = 10, /// 64-bit IEEE 754 floating point number
    BAMP_TYPE_STRING = 11  /// Null-terminated character string
} bamp_type;

/**
 * Typed value. This is used to transmit values along with their type
 * ID.
 */
typedef struct
{
    bamp_type type;  /// Type of the value
    size_t    refs;  /// Reference counter
    union
    {
        uint8_t  u8;
        uint16_t u16;
        uint32_t u32;
        uint64_t u64;
        int8_t   i8;
        int16_t  i16;
        int32_t  i32;
        int64_t  i64;
        float    f32;
        double   f64;
        char*    str;
    } value;
} bamp_value;


bamp_rc bamp_value_type_to_str  (bamp_type type, const char** str);
bamp_rc bamp_value_type_from_str(bamp_type* type, const char* str);
bamp_rc bamp_value_to_new_str   (const bamp_value* value, char** str);

bamp_rc bamp_value_new_from_str (bamp_value** value, const char* str,
                                 bamp_type type);

bamp_rc bamp_value_new(bamp_value** value);
bamp_rc bamp_value_clone(bamp_value** dst, const bamp_value* src);
bamp_rc bamp_value_ref(bamp_value* value);
bamp_rc bamp_value_unref(bamp_value* value);

bamp_rc bamp_value_set_null(bamp_value* value);
bamp_rc bamp_value_set_u8  (bamp_value* value, uint8_t  u8);
bamp_rc bamp_value_set_u16 (bamp_value* value, uint16_t u16);
bamp_rc bamp_value_set_u32 (bamp_value* value, uint32_t u32);
bamp_rc bamp_value_set_u64 (bamp_value* value, uint64_t u64);
bamp_rc bamp_value_set_i8  (bamp_value* value, int8_t   i8);
bamp_rc bamp_value_set_i16 (bamp_value* value, int16_t  i16);
bamp_rc bamp_value_set_i32 (bamp_value* value, int32_t  i32);
bamp_rc bamp_value_set_i64 (bamp_value* value, int64_t  i64);
bamp_rc bamp_value_set_f32 (bamp_value* value, float    f32);
bamp_rc bamp_value_set_f64 (bamp_value* value, double   f64);
bamp_rc bamp_value_set_str (bamp_value* value, const char* str);

bamp_rc bamp_value_get_type(const bamp_value* value, bamp_type* type);
bamp_rc bamp_value_is_null (const bamp_value* value, int*       is_null);
bamp_rc bamp_value_get_u8  (const bamp_value* value, uint8_t*   u8);
bamp_rc bamp_value_get_u16 (const bamp_value* value, uint16_t*  u16);
bamp_rc bamp_value_get_u32 (const bamp_value* value, uint32_t*  u32);
bamp_rc bamp_value_get_u64 (const bamp_value* value, uint64_t*  u64);
bamp_rc bamp_value_get_i8  (const bamp_value* value, int8_t*    i8);
bamp_rc bamp_value_get_i16 (const bamp_value* value, int16_t*   i16);
bamp_rc bamp_value_get_i32 (const bamp_value* value, int32_t*   i32);
bamp_rc bamp_value_get_i64 (const bamp_value* value, int64_t*   i64);
bamp_rc bamp_value_get_f32 (const bamp_value* value, float*     f32);
bamp_rc bamp_value_get_f64 (const bamp_value* value, double*    f64);
bamp_rc bamp_value_get_str (const bamp_value* value, char**     str);

#ifdef __cplusplus
}
#endif

#endif // __BAMP_VALUE_H__
